#include "Predicate.h"

typedef std::multimap<std::string, Predicate*> ChMul;
Predicate::Predicate()
{
	name.clear();
	attr.clear();
	father = NULL;
	child.clear();
};
Predicate::~Predicate()
{
	if( child.size() > 0 )
	{
		for( std::multimap<std::string, Predicate*>::iterator chit = child.begin();
			chit != child.end(); chit ++ )
		{
			Predicate* p = (*chit).second;
			if( p )
			{
				delete p;
				p = NULL;
			}
		}
	}
}
void Predicate::Show()
{
	std::cout << " --- Show --- \n";
	std::cout << "Name " << name << "\n";
	std::cout << "Value: ";
	for( unsigned int i = 0; i < attr.size(); i ++ )
	{
		std::cout << attr.at(i) << " ";
	}
	std::cout << "\n";
	std::cout << "child size " << child.size() << "\n";
}
void Predicate::ShowAll()
{
	Show();
	for( ChMul::iterator childIt = child.begin(); childIt != child.end(); childIt ++ )
	{
		Predicate * tempPred = (*childIt).second;
		tempPred->ShowAll();
	}	
}
void Predicate::Print( std::string &output )
{
	int depth = Depth();

	std::string depth_blank_1;
	std::string depth_blank_2;
	for( int i = 0; i < depth; i ++ )
	{
		depth_blank_1.append( "-" );
		depth_blank_2.append( "+" );
	}

	output.append( depth_blank_1 );
	output.append( name );
	output.append( "\n");
	output.append( depth_blank_2 );
	output.append( "+" );

	for( unsigned int i = 0; i < attr.size(); i ++ )
	{
		output.append( attr.at(i) );
		output.append( " " );
	}
	output.append( "\n" );
}
void Predicate::PrintAll( std::string &output )
{
	Print( output );
	for( ChMul::iterator childIt = child.begin(); childIt != child.end(); childIt ++ )
	{
		Predicate * tempPred = (*childIt).second;
		tempPred->PrintAll( output );
	}
}
void Predicate::AddValue(const std::string& value) 
{
	attr.push_back(value);
}
void Predicate::AddChild(const std::string& name, Predicate *pred) 
{
	child.insert(make_pair(name, pred));
}
bool Predicate::GetValue(const std::string& name, std::vector<std::string>& value) 
{
	value = attr;
  	if( child.size() < 1 )
   	{
   		value = attr;
   	}
   	else
   	{
  		std::multimap<std::string,Predicate*>::iterator it = child.find(name);
   
   		if (it == child.end()) 
   		{
   			return false;
   		}
   
   		value = (it->second)->attr;
   	}

	return true;
}
bool Predicate::GetValue(const std::string& name, std::string& value) 
{
	std::vector <std::string> vv;

	if (GetValue(name, vv) == false || vv.size() < 1) 
	{
		return false;
	}

	value = vv[0];

	return true;

}
bool Predicate::GetValue(const std::string& name, float& value) 
{
	std::string vv;

	if (GetValue(name, vv) == false) 
	{
		return false;
	}

	value = (float)atof(vv.data());

	return true;
}
bool Predicate::GetValue(const std::string& name, int& value) 
{
	std::string vv;

	if (GetValue(name, vv) == false) 
	{
		return false;
	}

	value = atoi(vv.data());

	return true;

}
bool Predicate::GetValue(const std::string& name, unsigned int& value) 
{
	std::string vv;

	if (GetValue(name, vv) == false) 
	{
		return false;
	}

	value = atoi(vv.data());

	return true;
}
bool Predicate::GetValue(const std::string& name, bool& value)
{
	std::string vv;

	if (GetValue(name, vv) == false) 
	{
		return false;
	}

	if( vv == "true" )
	{
		value = true;
	}
	else if ( vv == "false" )
	{
		value = false;
	}
	else
	{
		return true;
	}

	return true;
}
bool Predicate::GetValue(const std::string& name, float *value, unsigned int arrayLen )
{
	std::vector<std::string> vv;

	if (GetValue(name, vv) == false) 
	{
		return false;
	}

	if (vv.size() < arrayLen) 
	{
		return false;
	}

	for (unsigned int i = 0; i < arrayLen; ++ i) 
	{
		value[i] = (float)atof(vv[i].data());
	}

	return true;

}
bool Predicate::GetValue(const std::string& name, int *value, unsigned int arrayLen)
{
	std::vector<std::string> vv;

	if( GetValue(name, vv) == false ) 
	{
		return false;
	}

	if( vv.size() < arrayLen ) 
	{
		return false;
	}

	for (unsigned int i = 0; i < arrayLen; ++ i) 
	{
		value[i] = (int)atoi(vv[i].data());
		//value[i] = (int)atoi()
	}

	return true;
}
int Predicate::Depth()
{
	int depth = 0;
	Predicate * this_father = father;
	while( this_father != NULL )
	{
		this_father = this_father->father;
		depth ++;
	}

	return depth;
}